import random, json, sys, os
from .chess import ChessBoard, board_key
from .score import win_score

def self_play(explorer, epsilon=0.2, choices=5, max_steps=200):
	chess_board = ChessBoard()
	history = []
	board_to_move = {}
	for i in range(max_steps):
		node = explorer.run(chess_board)
		assert len(node.moves) > 0 and node.best_move is not None
		key = board_key(chess_board)
		if random.random() < epsilon:
			moves = [m for m in node.moves if m[0]!=-win_score] # 不能走直接输的步
			if len(moves)==0: moves = node.moves # 如果所有步都直接输
			moves = sorted(moves, key=lambda m: m[0], reverse=True)
			move = random.choice(moves[:choices])[1] # 从最好的choices=5步中选
		else:
			move = node.best_move
			if key in board_to_move and board_to_move[key]==move and len(node.moves)>1:
				# 不允许走重复局面的相同步
				moves = sorted(node.moves, key=lambda m: m[0], reverse=True)
				moves = [m for m in moves[:2] if m!=move][0][1]
		board_to_move[key] = move
		i1,j1,i2,j2 = move[2:]			
		chess = chess_board.board_map[(i1,j1)]
		assert chess.can_move_to(i2,j2)
		chess.x, chess.y = i2, j2
		del chess_board.board_map[(i1,j1)]
		captured = None
		if (i2,j2) in chess_board.board_map:
			captured = chess_board.board_map[(i2,j2)]
			del chess_board.board_map[(i2,j2)]
		chess_board.board_map[(i2,j2)] = chess
		chess_board.rotate_board()
		captured = '_' if captured is None else captured.type
		move = (i+1,) + move[1:] + (captured,)
		history.append(move)
		print(move)
		if captured=='King':
			break
	return history

def load_history(filename):
	moves = []
	with open(filename) as fp:
		for line in fp:
			line = line.split(',')
			if len(line)==0: continue
			assert len(line)==7
			moves.append([int(m) for m in line[2:6]])
	history = []
	chess_board = ChessBoard()
	for step, move in enumerate(moves):
		key = board_key(chess_board)
		i1,j1,i2,j2 = move
		if step%2==1:
			i1,j1,i2,j2 = 8-i1,9-j1,8-i2,9-j2
		chess1 = chess_board.board_map[(i1,j1)]
		# assert chess1.can_move_to(i2,j2)
		chess1.x, chess1.y = i2, j2
		del chess_board.board_map[(i1,j1)]
		captured = None
		if (i2,j2) in chess_board.board_map:
			captured = chess_board.board_map[(i2,j2)]
		chess_board.board_map[(i2,j2)] = chess1
		history.append([key, move, captured])
	history.append([board_key(chess_board), None, None])
	return history

def run(program_id, games, use_alpha_beta=True):
	if use_alpha_beta:
		from .alpha_beta import BoardExplorer
		explorer = BoardExplorer(4, 20, 10) # 搜索最小/大深度，搜索最少秒数
	else:
		from .min_max import BoardExplorer
		explorer = BoardExplorer(3)
	if not os.path.isdir(program_id):
		os.mkdir(program_id)
	cache_path = f'{program_id}/cache.json'
	if os.path.isdir(cache_path):
		explorer.cache.load(cache_path)
	for i in range(games):
		result = f'{program_id}/{i+1}.csv' # 
		if os.path.isfile(result):
			continue
		hisory = self_play(explorer)
		with open(result, 'w') as fp:
			for move in hisory:
				fp.write(','.join([str(x) for x in move])+'\n')
		explorer.cache.save(cache_path)

if __name__ == '__main__':
	run(sys.argv[1], 100)
	# print(load_history('1/1.csv'))

# 生成历史信息:
# 在不同窗口(<8个)中运行下面命令，每个窗口使用不同的program_id，运行结果将被保存到名为program_id的目录中
# 运行命令 python3 -m web.py_lib.self_play [program_id]

# 读取历史信息:
# print(load_history('1/1.csv'))

